import sys
import time
from datetime import datetime

from PyQt5 import QtNetwork, QtCore, QtWidgets
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QTextCursor


class ConnectionWidget(QtWidgets.QWidget):
    """TCP/UDP连接部件"""

    def __init__(self, parent=None):
        super().__init__(parent)

        self.protocol_combo = QtWidgets.QComboBox(self)
        self.protocol_combo.addItem("TCP")
        self.protocol_combo.addItem("UDP")

        self.local_port_edit = QtWidgets.QLineEdit(self)
        self.local_port_edit.setPlaceholderText("本地端口")

        self.remote_ip_edit = QtWidgets.QLineEdit(self)
        self.remote_ip_edit.setPlaceholderText("远程IP地址")

        self.remote_port_edit = QtWidgets.QLineEdit(self)
        self.remote_port_edit.setPlaceholderText("远程端口")

        self.connect_btn = QtWidgets.QPushButton("连接", self)

        layout = QtWidgets.QHBoxLayout()
        layout.addWidget(QtWidgets.QLabel("协议："))
        layout.addWidget(self.protocol_combo)
        layout.addWidget(QtWidgets.QLabel("本地端口："))
        layout.addWidget(self.local_port_edit)
        layout.addWidget(QtWidgets.QLabel("远程IP地址："))
        layout.addWidget(self.remote_ip_edit)
        layout.addWidget(QtWidgets.QLabel("远程端口："))
        layout.addWidget(self.remote_port_edit)
        layout.addWidget(self.connect_btn)
        self.setLayout(layout)


class SendWidget(QtWidgets.QWidget):
    """消息发送部件"""

    def __init__(self, parent=None):
        super().__init__(parent)

        self.send_file_btn = QtWidgets.QPushButton("发送文件", self)
        self.send_btn = QtWidgets.QPushButton("发送", self)

        self.send_msg_edit = QtWidgets.QTextEdit(self)
        self.send_msg_edit.setMaximumHeight(60)
        self.send_msg_edit.setPlaceholderText("请输入要发送的消息")

        self.send_interval_edit = QtWidgets.QLineEdit(self)
        self.send_interval_edit.setPlaceholderText("定时发送间隔（秒）")
        self.send_interval_edit.setMaximumWidth(100)

        layout = QtWidgets.QHBoxLayout()
        layout.addWidget(self.send_file_btn)
        layout.addWidget(self.send_msg_edit)
        layout.addWidget(self.send_interval_edit)
        layout.addWidget(self.send_btn)
        self.setLayout(layout)


class ReceiveWidget(QtWidgets.QWidget):
    """消息接收部件"""

    def __init__(self, parent=None):
        super().__init__(parent)

        self.receive_msg_edit = QtWidgets.QTextEdit(self)
        self.receive_msg_edit.setReadOnly(True)

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(QtWidgets.QLabel("接收到的消息："))
        layout.addWidget(self.receive_msg_edit)
        self.setLayout(layout)


# class MessageProcessingMainSwitch(QtWidgets.QWidget):
#     """报文处理部分"""
#
#     def __init__(self, parent=None):
#         super(MessageProcessingMainSwitch, self).__init__(parent)
#         layout = QtWidgets.QCheckBox()
#         layout.setText("是否")
#         layout.setChecked(False)
#         layout.setCheckState(Qt.PartiallyChecked)
#         self.setLayout(layout)
#         # self.msg_switch.


class MainWindow(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()

        self.tcp_socket = None
        self.udp_socket = None
        self.setWindowTitle("TCP/UDP工具")
        self.connection_widget = ConnectionWidget(self)
        self.send_widget = SendWidget(self)
        self.receive_widget = ReceiveWidget(self)
        # self.message_processing_main_switch = MessageProcessingMainSwitch(self)

        main_layout = QtWidgets.QVBoxLayout()
        main_layout.addWidget(self.connection_widget)
        main_layout.addWidget(self.send_widget)
        main_layout.addWidget(self.receive_widget)
        # main_layout.addWidget(self.message_processing_main_switch)
        self.setLayout(main_layout)

        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.send_message)

        self.connection_widget.connect_btn.clicked.connect(self.connect_to_server)
        self.send_widget.send_file_btn.clicked.connect(self.select_file)
        self.send_widget.send_btn.clicked.connect(self.send_message)

    def connect_to_server(self):
        """连接到远程服务器"""
        protocol = self.connection_widget.protocol_combo.currentText()
        local_port = int(self.connection_widget.local_port_edit.text())
        remote_ip = self.connection_widget.remote_ip_edit.text()
        remote_port = int(self.connection_widget.remote_port_edit.text())
        if self.connection_widget.connect_btn.text() == "连接":
            if protocol == "TCP":
                self.tcp_socket = QtNetwork.QTcpSocket(self)
                self.tcp_socket.readyRead.connect(self.receive_message)
                self.tcp_socket.connectToHost(remote_ip, remote_port)

            elif protocol == "UDP":
                self.udp_socket = QtNetwork.QUdpSocket(self)
                self.udp_socket.readyRead.connect(self.receive_message)
                self.udp_socket.bind(QtNetwork.QHostAddress.Any, local_port)
                self.udp_socket.connectToHost(remote_ip, remote_port)

            self.receive_widget.receive_msg_edit.insertPlainText(
                "连接：{} 成功 \n".format(remote_ip)
            )
            # self.connection_widget.connect_btn.setEnabled(False)
            self.connection_widget.connect_btn.setText("断开连接")
        elif self.connection_widget.connect_btn.text() == "断开连接":
            if protocol == "TCP":
                self.tcp_socket.close()
            elif protocol == "UDP":
                self.udp_socket.close()
            self.receive_widget.receive_msg_edit.insertPlainText(f"断开连接：{remote_ip} \n")
            self.receive_widget.receive_msg_edit.insertPlainText(self.size())
            self.connection_widget.connect_btn.setText("连接")

            # self.udp_socket.disconnectFromHost(remote_ip, remote_port)

    def select_file(self):
        """选择要发送的文件"""
        file_dialog = QtWidgets.QFileDialog()
        file_name, _ = file_dialog.getOpenFileName(self, "选择要发送的文件")
        with open(file_name, "r") as f:
            self.send_widget.send_msg_edit.setPlainText(f.read())

    def send_message(self):
        """发送消息"""
        protocol = self.connection_widget.protocol_combo.currentText()

        if protocol == "TCP":
            self.tcp_socket.write(self.send_widget.send_msg_edit.toPlainText().encode())

        elif protocol == "UDP":
            self.udp_socket.writeDatagram(
                self.send_widget.send_msg_edit.toPlainText().encode(),
                QtNetwork.QHostAddress(self.connection_widget.remote_ip_edit.text()),
                int(self.connection_widget.remote_port_edit.text()),
            )

        self.receive_widget.receive_msg_edit.moveCursor(QTextCursor.End)
        self.receive_widget.receive_msg_edit.insertPlainText(
            f"发送：{self.send_widget.send_msg_edit.toPlainText()}\n"
        )
        # self.send_widget.send_msg_edit.clear()

    def receive_message(self):
        """接收到消息"""
        protocol = self.connection_widget.protocol_combo.currentText()

        if protocol == "TCP":
            while self.tcp_socket.canReadLine():
                message = self.tcp_socket.readLine().data().decode()
                self.receive_widget.receive_msg_edit.moveCursor(QTextCursor.End)
                self.receive_widget.receive_msg_edit.insertPlainText(
                    f"{datetime.now().timestamp()}，接收：{message}"
                )

        elif protocol == "UDP":
            while self.udp_socket.hasPendingDatagrams():
                datagram, _, _ = self.udp_socket.readDatagram(
                    self.udp_socket.pendingDatagramSize()
                )
                message = datagram.data().decode()
                self.receive_widget.receive_msg_edit.moveCursor(QTextCursor.End)
                self.receive_widget.receive_msg_edit.insertPlainText(
                    f"{datetime.now().timestamp()}，接收：{message}"
                )

    def send_interval_changed(self):
        """定时发送间隔改变"""
        interval = int(self.send_widget.send_interval_edit.text())
        if interval > 0:
            self.timer.start(interval * 1000)
        else:
            self.timer.stop()


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())
